package main

import "fmt"

type Rectangle struct {
	x, y  int
	w, h  int
	areas int
}

func (r *Rectangle) Area() int {
	r.areas = r.w * r.h
	return r.areas
}

func (r Rectangle) Areas() int {
	r.areas = r.w * r.h
	return r.areas
}

func Area(r Rectangle) int {
	r.areas = r.w * r.h
	return r.areas
}

type ICall interface {
	Call()
}

// inherit
type A struct {
	Name string
}

func (this *A) Call() {
	if this == nil {
		fmt.Println("A is nil")
	}
	fmt.Println("A Call", this.Name)
}

type B struct {
	*A
	Name string
}

func (this *B) Call() {
	fmt.Println("B Call")
}

type C struct {
	A
	Name string
}

func (this *C) Call() {
	fmt.Println("C Call")
}

type D struct {
	A
}

func main() {
	r1 := Rectangle{w: 10, h: 10}
	fmt.Println(r1)
	fmt.Println(r1.Area())
	fmt.Println(r1)
	r1.areas = 10
	fmt.Println(r1)

	fmt.Println("--------")

	r2 := Rectangle{w: 10, h: 10}
	fmt.Println(r2)
	fmt.Println(Area(r2))
	fmt.Println(r2)

	fmt.Println("--------")

	r3 := &Rectangle{w: 10, h: 10}
	fmt.Println(r3)
	fmt.Println(r3.Area())
	fmt.Println(r3)

	fmt.Println("--------")

	a := A{}
	b := B{&a, ""}
	b.Name = "Astone"
	b.A.Name = "Chou"
	fmt.Println(b)
	fmt.Println(b.A.Name)

	c := C{a, ""}
	c.Name = "Astone"
	c.A.Name = "Chou"
	fmt.Println(c)
	fmt.Println(c.A.Name)

	d := D{a}

	d2 := D{}
	d2.Name = "cc"

	// interface
	var i ICall
	i = &a
	i.Call()
	i = &b
	i.Call()
	i = &c
	i.Call()
	i = &d
	i.Call()
	i = &d2
	i.Call()
}
